package it.unipi.di.rasip.protocol;

import it.unipi.di.rasip.Chat;
import it.unipi.di.rasip.RasipUser;
import it.unipi.di.rasip.gui.chat.ChatManager;

import java.util.Hashtable;

/** LA classe si pone come intermediario fra il sistema grafico e i vari
 * client che il sistema supporta;
 * I thread, uno per ogni comunicazione, possono essere anche di client diversi {sip, ecc}
 * al fine della classe questo non ha importanza.  Tutti i client implementano la medesima
 * interfaccia BusInterface attraverso la quale è possibile forwardare le richieste.  
 * 
 * @author paolo
 *
 */
public class Mediator {
	private static Mediator _instance = null;
	private static Hashtable threadClientTable;
	private static Hashtable chatTable;
	
	public static Mediator getInstance () {
		if (_instance == null) {
			_instance = new Mediator();
		}
		return _instance;
	}
	
	private Mediator() {
		threadClientTable = new Hashtable();
		chatTable = new Hashtable();
	}
	
	/** I client raccolti in una hash table sono recuperabili mediante la chiave passata
	 * in input; la prima volta viene instanziato l'oggetto e caricato nella tabella.
	 * @param uri
	 * @return
	 */ 
	public BusInterface getClient (String uri) throws RasipException {
		BusInterface localSc;
		if ( (localSc = (BusInterface) threadClientTable.get(uri)) == null) {
			if (uri.startsWith("sip")) {
				SipServer ss = SipServer.getInstance();
				localSc = (BusInterface) new SipClient(uri, ss.getScn() );
			} else {
				throw new RasipException ("Protocollo non supportato: " + uri );
			}
			
			threadClientTable.put(uri, localSc);
			localSc.start();
			System.out.println("Creato un'altro per:" + uri);
		}
		return localSc;
	}
	
	public Chat getChat(String uri) {
		Chat c;
		if(null == (c = (Chat) chatTable.get(uri))) {
			c = new Chat(RasipUser.rasipUserFromURI(uri), RasipUser.getLocalUser().getUsername());
			this.addChat(c, uri);
			ChatManager.getInstance().newChat(c);
		}
		
		return c;
	}
	
	public void addChat(Chat c, String uri) {
		chatTable.put(uri, c);
	}
	
	/** Invia il messaggio
	 * 
	 * @param uri
	 * @param msg
	 * @throws RasipException
	 */
	public void sendMessage( RasipUser user, String msg ) throws RasipException {
		System.out.println("sendMessage( RasipUser user, String msg ");
		//getClient(user.getCompleteURI()).sendInvite( user.getUsername(),  msg );
		getClient(user.getCompleteURI()).sendMessage( RasipUser.getLocalUser().getCompleteURI(),  msg );
	}
	
	public void receiveMessage (String toURI, String fromURI, String msg) {
		// Verifica che l'user locale sia stato creato
		if (RasipUser.getLocalUser() == null) {		
			RasipUser.setLocalUser(RasipUser.rasipUserFromURI(toURI));
		}
		//System.out.println("MSG: " + uri + ": "+ msg);
		Chat c = (Chat)this.getChat(fromURI);
		c.receiveMessage(msg);
	}
	
	
	/** Notifica da parte del cliente; es:
	 * - Timeout scaduto
	 * @param uri
	 */
	public void alert ( String uri, int code ) {
		System.out.println("ALERT: " + code + "-->" + (code == 200?"ok":""));
		//ChatManager.getInstance()...
	}
}

